<?php
class system_captcha {
	private $_code = null;	
	private $_width;
	private $_height;
	private $_font;
	private $_namespace = 'default';
	private static $cns = 'CU8FKG7GFVNT';

	public function __construct($namespace = 'default', $width = 80, $height = 24, $font = 5) {
		$this->_width = $width;
		$this->_height = $height;
		$this->_font = $font;
		$this->_namespace = $namespace;
	}
	
	private static $_instance = null;
	/**
	 * @return system_captcha
	 * @param unknown_type $width
	 * @param unknown_type $height
	 * @param unknown_type $font
	 */
	public static function getInstance($namespace = 'default', $width = 80, $height = 24, $font = 5) {
		if(self::$_instance === null) {
			self::$_instance = new self($namespace, $width, $height, $font);
		}
		return self::$_instance;
	}
	
	public static function auth($code, $namespace = 'default') {
		$_code = system_session::namespaceGet($namespace);
		if(!$_code || (is_array($_code[self::$cns]) && !isset($_code[self::$cns]))) {
			return false;
		}
		$result = md5($_code[self::$cns]) === md5($code);
		system_session::namespaceUnset($namespace);
		return $result;
	}
	
	public function getCode() {
		if($this->_code === null) {
			$this->setCode();
		}
		return $this->_code;
	}
	
	/**
	 * @return system_captcha
	 * @param unknown_type $length
	 */
	public function setCode($length = 6) {
		$glbVerifySeed = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";
		$bgnIdx = 0;
		$endIdx = strlen($glbVerifySeed) - 1;
		
		$code = "";
		for($i = 0; $i < $length; $i++) {
			$curPos = rand($bgnIdx, $endIdx);
			$code .= substr($glbVerifySeed, $curPos, 1);
		}
		$this->_code = $code;
		$session = new system_session_namespace($this->_namespace);
		$session->{self::$cns} = $code;
		$session->lock();
		return $this;
	}
	
	/**
	 * 输出校验码图像
	 * @param unknown_type $imgFgColorArr
	 * @param unknown_type $imgBgColorArr
	 * @return system_captcha
	 */
	public function display($imgFgColorArr=array(0,0,0), $imgBgColorArr=array(255,255,255)) {
		$imgString = $this->getCode();
		$imgWidth = $this->_width;
		$imgHeight = $this->_height;
		$imgFont = $this->_font;
		$image = imagecreatetruecolor($imgWidth, $imgHeight);
		
		//用白色背景加黑色边框画个方框
		$backColor = imagecolorallocate($image, 255, 255, 255);
		$borderColor = imagecolorallocate($image, 0, 0, 0);
		imagefilledrectangle($image, 0, 0, $imgWidth - 1, $imgHeight - 1, $backColor);
		imagerectangle($image, 0, 0, $imgWidth - 1, $imgHeight - 1, $borderColor);
		
		$imgFgColor = imagecolorallocate($image, $imgFgColorArr[0], $imgFgColorArr[1], $imgFgColorArr[2]);
		$this->doDrawStr($image, $imgString, $imgFgColor, $imgFont);
		$this->doPollute($image, 64);
		
		header('Content-type: image/png');
		imagepng($image);
		imagedestroy($image);
		return $this;
	}

	//画出校验码
	private function doDrawStr($image, $string, $color, $imgFont) {
		$imgWidth = imagesx($image);
		$imgHeight = imagesy($image);		
		$count = strlen($string);		
		$x = ($imgWidth - (imagefontwidth(5) * $count)) / 2;
		$y = ($imgHeight - imagefontheight(5)) / 2;
		imagestring($image, $imgFont, $x, $y, $string, $color);		
		return 0;
	}
	
	//画出一些杂点
	private function doPollute($image, $times) {
		$imgWidth = imagesx($image);
		$imgHeight = imagesy($image);
		for($j = 0; $j < $times; $j++) {
			$x = rand(0, $imgWidth);
			$y = rand(0, $imgHeight);			
			$color = imagecolorallocate($image, rand(0, 255), rand(0, 255), rand(0, 255));
			imagesetpixel($image, $x, $y, $color);
		}
	}
}
